/**
 * @file flip_carry_sse_32.c
 *
 * This module deals with flipping discs.
 *
 * A function is provided for each square of the board. These functions are
 * gathered into an array of functions, so that a fast access to each function
 * is allowed. The generic form of the function take as input the player and
 * the opponent bitboards and return the flipped squares into a bitboard.
 *
 * Given the following notation:
 *  - x = square where we play,
 *  - P = player's disc pattern,
 *  - O = opponent's disc pattern,
 * the basic principle is to read into an array the result of a move. Doing
 * this is easier for a single line ; so we can use arrays of the form:
 *  - ARRAY[x][8-bits disc pattern].
 * The problem is thus to convert any line of a 64-bits disc pattern into an
 * 8-bits disc pattern. A fast way to do this is to select the right line,
 * with a bit-mask, to gather the masked-bits into a continuous set by a simple
 * multiplication and to right-shift the result to scale it into a number
 * between 0 and 255.
 * Once we get our 8-bits disc patterns,a first array (OUTFLANK) is used to
 * get the player's discs that surround the opponent discs:
 *  - outflank = OUTFLANK[x][O] & P
 * (Only inner 6-bits of the P are in interest here.)
 * The result is then used as an index to access a second array giving the
 * flipped discs according to the surrounding player's discs:
 *  - flipped = FLIPPED[x][outflank].
 * (Flipped discs fall into inner 6-bits.)
 * Finally, a precomputed array transform the inner 6-bits disc pattern back into a
 * 64-bits disc pattern, and the flipped squares for each line are gathered and
 * returned to generate moves.
 *
 * If the OUTFLANK search is in LSB to MSB direction, carry propagation 
 * can be used to determine contiguous discs.
 *
 * @date 1998 - 2014
 * @author Richard Delorme
 * @author Toshihiko Okuhara
 * @version 4.4
 */

#include <string.h>	// memcpy

#define	ULL(H,L)	(((unsigned long long) (H) << 32) | (L))

/** outflank array (indexed with inner 6 bits) */
/* static const unsigned char OUTFLANK_0[64] = {
	0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x20,
	0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x40,
	0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x20,
	0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x80
}; */

/* static const unsigned char OUTFLANK_1[64] = {
	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00,
	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00,
	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00,
	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00
}; */

static const unsigned char OUTFLANK_2[64] = {
	0x00, 0x01, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x20, 0x21, 0x00, 0x00,
	0x00, 0x01, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40, 0x41, 0x00, 0x00,
	0x00, 0x01, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x20, 0x21, 0x00, 0x00,
	0x00, 0x01, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x81, 0x00, 0x00
};

static const unsigned char OUTFLANK_3[64] = {
	0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x22, 0x21, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x42, 0x41, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x22, 0x21, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x82, 0x81, 0x00, 0x00, 0x00, 0x00
};

static const unsigned char OUTFLANK_4[64] = {
	0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x40, 0x40, 0x40, 0x40, 0x44, 0x44, 0x42, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x80, 0x80, 0x80, 0x80, 0x84, 0x84, 0x82, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static const unsigned char OUTFLANK_5[64] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x01,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x88, 0x88, 0x88, 0x88, 0x84, 0x84, 0x82, 0x81,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/* static const unsigned char OUTFLANK_6[64] = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x01,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; */

static const unsigned int OUTFLANK_7[64] = {	// accessed with movd
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x01
};

/** flip array (indexed with outflank, returns inner 6 bits) */
static const unsigned long long FLIPPED_2_H[130] = {
	0x0000000000000000ULL, 0x0202020202020202ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0808080808080808ULL, 0x0a0a0a0a0a0a0a0aULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x1818181818181818ULL, 0x1a1a1a1a1a1a1a1aULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x3838383838383838ULL, 0x3a3a3a3a3a3a3a3aULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x7878787878787878ULL, 0x7a7a7a7a7a7a7a7aULL
};

static const unsigned long long FLIPPED_3_H[131] = {
	0x0000000000000000ULL, 0x0606060606060606ULL, 0x0404040404040404ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x1010101010101010ULL, 0x1616161616161616ULL, 0x1414141414141414ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x3030303030303030ULL, 0x3636363636363636ULL, 0x3434343434343434ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x7070707070707070ULL, 0x7676767676767676ULL, 0x7474747474747474ULL
};

static const unsigned long long FLIPPED_4_H[133] = {
	0x0000000000000000ULL, 0x0e0e0e0e0e0e0e0eULL, 0x0c0c0c0c0c0c0c0cULL, 0x0000000000000000ULL, 0x0808080808080808ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x2020202020202020ULL, 0x2e2e2e2e2e2e2e2eULL, 0x2c2c2c2c2c2c2c2cULL, 0x0000000000000000ULL, 0x2828282828282828ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x6060606060606060ULL, 0x6e6e6e6e6e6e6e6eULL, 0x6c6c6c6c6c6c6c6cULL, 0x0000000000000000ULL, 0x6868686868686868ULL
};

static const unsigned long long FLIPPED_5_H[137] = {
	0x0000000000000000ULL, 0x1e1e1e1e1e1e1e1eULL, 0x1c1c1c1c1c1c1c1cULL, 0x0000000000000000ULL, 0x1818181818181818ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x1010101010101010ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x4040404040404040ULL, 0x5e5e5e5e5e5e5e5eULL, 0x5c5c5c5c5c5c5c5cULL, 0x0000000000000000ULL, 0x5858585858585858ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x5050505050505050ULL
};

static const unsigned long long FLIPPED_3_V[131] = {
	0x0000000000000000ULL, 0x0000000000ffff00ULL, 0x0000000000ff0000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x000000ff00000000ULL, 0x000000ff00ffff00ULL, 0x000000ff00ff0000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000ffff00000000ULL, 0x0000ffff00ffff00ULL, 0x0000ffff00ff0000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x00ffffff00000000ULL, 0x00ffffff00ffff00ULL, 0x00ffffff00ff0000ULL
};

static const unsigned long long FLIPPED_4_V[133] = {
	0x0000000000000000ULL, 0x00000000ffffff00ULL, 0x00000000ffff0000ULL, 0x0000000000000000ULL, 0x00000000ff000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000ff0000000000ULL, 0x0000ff00ffffff00ULL, 0x0000ff00ffff0000ULL, 0x0000000000000000ULL, 0x0000ff00ff000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x00ffff0000000000ULL, 0x00ffff00ffffff00ULL, 0x00ffff00ffff0000ULL, 0x0000000000000000ULL, 0x00ffff00ff000000ULL
};

static const unsigned long long  FLIPPED_5_V[137] = {
	0x0000000000000000ULL, 0x000000ffffffff00ULL, 0x000000ffffff0000ULL, 0x0000000000000000ULL, 0x000000ffff000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x000000ff00000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x00ff000000000000ULL, 0x00ff00ffffffff00ULL, 0x00ff00ffffff0000ULL, 0x0000000000000000ULL, 0x00ff00ffff000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
	0x00ff00ff00000000ULL
};

#ifdef USE_GAS_MMX

#ifdef hasSSE2
	#include <emmintrin.h>
	#define	SSE2
#else
	#pragma GCC push_options
	#pragma GCC target ("sse2")
	#include <emmintrin.h>
	#pragma GCC pop_options
	#define	SSE2	/* __attribute__ ((__target__ ("sse2"))) */	// seems still buggy, 
		// therefore SSE intrinsics cannot be used in dispatching version.
#endif

static const __v2di	minusone = { -1LL, -1LL };

#if 0 // hasMMX, hasSSE2
static const unsigned long long mask_c1c8 = 0x0404040404040404ULL;
static const unsigned long long mask_d1d8 = 0x0808080808080808ULL;
static const unsigned long long mask_e1e8 = 0x1010101010101010ULL;
static const unsigned long long mask_f1f8 = 0x2020202020202020ULL;

static const unsigned long long mask_a4h4 = 0x00000000ff000000ULL;
static const unsigned long long mask_a5h5 = 0x000000ff00000000ULL;

static const unsigned long long mask_f1a6 = 0x0000010204081020ULL;
static const unsigned long long mask_g1a7 = 0x0001020408102040ULL;
static const unsigned long long mask_h1a8 = 0x0102040810204080ULL;
static const unsigned long long mask_h2b8 = 0x0204081020408000ULL;
static const unsigned long long mask_h3c8 = 0x0408102040800000ULL;

static const unsigned long long mask_a3f8 = 0x2010080402010000ULL;
static const unsigned long long mask_a2g8 = 0x4020100804020100ULL;
static const unsigned long long mask_a1h8 = 0x8040201008040201ULL;
static const unsigned long long mask_b1h7 = 0x0080402010080402ULL;
static const unsigned long long mask_c1h6 = 0x0000804020100804ULL;
#endif

#define	SWAP64	0x4e	// for _mm_shuffle_epi32
#define	SWAP32	0xb1

/**
 * Make inverted flip mask if opponent's disc are surrounded by player's.
 *
 * 0xffffffffffffffffULL (-1) if outflank is 0
 * 0x0000000000000000ULL ( 0) if a 1 is in 64 bit
 */
static inline __v2di SSE2 flipmask (__v2di outflank) {
	return _mm_cmpeq_epi32(_mm_shuffle_epi32(outflank, SWAP32), outflank);
}

/**
 * _mm_set1_epi64x equivalent to utilize store to load forwarding
 *
 * AMD 47414 pp.96
 */
static inline __v2di SSE2 set1_by_movd (unsigned int L, unsigned int H) {
	__v2di	Y;
	Y = _mm_unpacklo_epi32(_mm_cvtsi32_si128(L), _mm_cvtsi32_si128(H));
	return _mm_unpacklo_epi64(Y, Y);
}

/**
 * _mm_movepi64_pi64 equivalent to avoid large-to-small mismatch
 *
 * AMD 47414 pp.96
 */
static inline unsigned long long SSE2 movepi64_by_movd(__v2di x)
{
#ifdef __SSE2__
	return ((unsigned int) _mm_cvtsi128_si32(x))
		| ((unsigned long long) _mm_cvtsi128_si32(_mm_srli_epi64(x, 32)) << 32);
#else
	unsigned long long y;
	__asm__ ( "movd	%1,%%eax\n\t"
		"psrlq	$32,%1\n\t"
		"movd	%1,%%edx"
		: "=A" (y) : "x" (x));
	return y;
#endif
}

#ifdef __SSE2__

#define FLIP_CARRY_2_VEC(flip_l)	__v2di	outflank_v_d;\
	outflank_v_d = _mm_andnot_si128(mask, (set1_by_movd(OL, OH) | mask) - minusone) & set1_by_movd(PL, PH);\
	outflank_v_d = _mm_andnot_si128(mask, outflank_v_d - (flipmask(outflank_v_d) - minusone));\
	outflank_v_d |= _mm_shuffle_epi32(outflank_v_d, SWAP64);\
	flipped = (flip_l) | movepi64_by_movd(outflank_v_d)

#define	FLIP_CARRY_3_VEC(flip_l)	__v2di	outflank_v_d, outflank_d_0, PP, OO, mask2_;\
	OO = set1_by_movd(OL, OH);\
	PP = set1_by_movd(PL, PH);\
	mask2_ = _mm_loadl_epi64((__m128i *) &mask2);\
	outflank_v_d = _mm_andnot_si128(mask01, (OO | mask01) - minusone) & PP;\
	outflank_d_0 = _mm_andnot_si128(mask2_, (OO | mask2_) - minusone) & PP;\
	outflank_v_d = _mm_andnot_si128(mask01, outflank_v_d - (flipmask(outflank_v_d) - minusone));\
	outflank_d_0 = _mm_andnot_si128(mask2_, outflank_d_0 - (flipmask(outflank_d_0) - minusone));\
	outflank_v_d |= _mm_shuffle_epi32(outflank_v_d, SWAP64) | outflank_d_0;\
	flipped = (flip_l) | movepi64_by_movd(outflank_v_d)

#else

#define FLIP_CARRY_2_VEC(flip_l)	__asm__ (\
		"movd	%1, %%xmm0\n\t"		"movd	%3, %%xmm1\n\t"\
		"movd	%2, %%xmm2\n\t"		"movd	%4, %%xmm3\n\t"\
		"punpckldq %%xmm2, %%xmm0\n\t"	"punpckldq %%xmm3, %%xmm1\n\t"\
		"movdqa	%5, %%xmm2\n\t"		"pcmpeqd %%xmm3, %%xmm3\n\t"\
		"punpcklqdq %%xmm0, %%xmm0\n\t"	"punpcklqdq %%xmm1, %%xmm1\n\t"\
		"por	%%xmm2, %%xmm1\n\t"	"movdqa	%%xmm2, %%xmm4\n\t"\
		"psubq	%%xmm3, %%xmm1\n\t"	"pandn	%%xmm0, %%xmm4\n\t"\
		"pand	%%xmm4, %%xmm1\n\t"\
		"pshufd	$177, %%xmm1, %%xmm0\n\t"\
		"pcmpeqd %%xmm1, %%xmm0\n\t"\
		"paddq	%%xmm3, %%xmm1\n\t"\
		"psubq	%%xmm0, %%xmm1\n\t"\
		"pandn	%%xmm1, %%xmm2\n\t"\
		"pshufd	$78, %%xmm2, %%xmm0\n\t"\
		"por	%%xmm2, %%xmm0\n\t"\
		"movd	%%xmm0, %%edx\n\t"	"psrlq	$32, %%xmm0\n\t"\
		"orl	%%edx, %%eax\n\t"	"movd	%%xmm0, %%edx"\
	: "=A" (flipped)\
	: "m" (PL), "m" (PH), "m" (OL), "m" (OH), "m" (mask), "a" (flip_l))

#define	FLIP_CARRY_3_VEC(flip_l)	__asm__ (\
		"movd	%1, %%xmm0\n\t"		"movd	%3, %%xmm1\n\t"		"pcmpeqd %%xmm6, %%xmm6\n\t"\
		"movd	%2, %%xmm2\n\t"		"movd	%4, %%xmm3\n\t"\
		"punpckldq %%xmm2, %%xmm0\n\t"	"punpckldq %%xmm3, %%xmm1\n\t"\
		"movdqa	%5, %%xmm2\n\t"		"movq	%6, %%xmm5\n\t"\
		"punpcklqdq %%xmm0, %%xmm0\n\t"	"punpcklqdq %%xmm1, %%xmm1\n\t"\
		"movdqa	%%xmm0, %%xmm3\n\t"	"movdqa	%%xmm1, %%xmm4\n\t"\
		"por	%%xmm2, %%xmm1\n\t"	"por	%%xmm5, %%xmm4\n\t"\
		"psubq	%%xmm6, %%xmm1\n\t"	"psubq	%%xmm6, %%xmm4\n\t"\
		"pand	%%xmm1, %%xmm0\n\t"	"pand	%%xmm4, %%xmm3\n\t"\
		"movdqa	%%xmm2, %%xmm1\n\t"	"movdqa	%%xmm5, %%xmm4\n\t"\
		"pandn	%%xmm0, %%xmm1\n\t"	"pandn	%%xmm3, %%xmm4\n\t"\
		"pshufd	$177, %%xmm1, %%xmm0\n\t"	"pshuflw $78, %%xmm4, %%xmm3\n\t"\
		"pcmpeqd %%xmm1, %%xmm0\n\t"	"pcmpeqd %%xmm4, %%xmm3\n\t"\
		"paddq	%%xmm6, %%xmm1\n\t"	"paddq	%%xmm6, %%xmm4\n\t"\
		"psubq	%%xmm0, %%xmm1\n\t"	"psubq	%%xmm3, %%xmm4\n\t"\
		"pandn	%%xmm1, %%xmm2\n\t"	"pandn	%%xmm4, %%xmm5\n\t"\
		"pshufd	$78, %%xmm2, %%xmm0\n\t"\
		"por	%%xmm2, %%xmm0\n\t"	"por	%%xmm5, %%xmm0\n\t"\
		"movd	%%xmm0, %%edx\n\t"	"psrlq	$32, %%xmm0\n\t"\
		"orl	%%edx, %%eax\n\t"	"movd	%%xmm0, %%edx"\
	: "=A" (flipped)\
	: "m" (PL), "m" (PH), "m" (OL), "m" (OH), "m" (mask01), "m" (mask2), "a" (flip_l))

#endif

#endif // USE_GAS_MMX

/**
 * Compute flipped discs when playing on square A1.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_A1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d9;

	outflank_v = ((ULL(OH, OL) | ~0x0101010101010100ULL) + 1) & ULL(PH, PL) & 0x0101010101010000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0001010101010100ULL;

	outflank_h = ((OL & 0x7e) + 0x02) & PL;
	flipped |= (outflank_h - (unsigned int) (outflank_h != 0)) & 0x7e;

	outflank_d9 = ((ULL(OH, OL) | ~0x8040201008040200ULL) + 1) & ULL(PH, PL) & 0x8040201008040000ULL;
	flipped |= (outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x0040201008040200ULL;

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_A1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x0101010101010100ULL, ~0x8040201008040200ULL };
	unsigned int outflank_h = ((OL & 0x7e) + 0x02) & PL;
	unsigned long long flipped;

	FLIP_CARRY_2_VEC((outflank_h - (unsigned int) (outflank_h != 0)) & 0x7e);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square B1.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_B1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d9;

	outflank_v = ((ULL(OH, OL) | ~0x0202020202020200ULL) + 1) & ULL(PH, PL) & 0x0202020202020000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0002020202020200ULL;

	outflank_h = ((OL & 0x7c) + 0x04) & PL;
	flipped |= (outflank_h - (unsigned int) (outflank_h != 0)) & 0x7c;

	outflank_d9 = ((ULL(OH, OL) | ~0x0080402010080400ULL) + 1) & ULL(PH, PL) & 0x0080402010080000ULL;
	flipped |= (outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x0000402010080400ULL;

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_B1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x0202020202020200ULL, ~0x0080402010080400ULL };
	unsigned int outflank_h = ((OL & 0x7c) + 0x04) & PL;
	unsigned long long flipped;

	FLIP_CARRY_2_VEC((outflank_h - (unsigned int) (outflank_h != 0)) & 0x7c);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square C1.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_C1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d9;

	outflank_v = ((ULL(OH, OL) | ~0x0404040404040400ULL) + 1) & ULL(PH, PL) & 0x0404040404040400ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0404040404040400ULL;

	outflank_h = OUTFLANK_2[(OL >> 1) & 0x3f] & PL;
	flipped |= (unsigned char) FLIPPED_2_H[outflank_h];

	flipped |= ((PL >> 7) & 0x00000200u & OL);

	outflank_d9 = ((ULL(OH, OL) | ~0x0000804020100800ULL) + 1) & ULL(PH, PL) & 0x0000804020100800ULL;
	flipped |= (outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x0000804020100800ULL;

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_C1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x0404040404040400ULL, ~0x0000804020100800ULL };
	unsigned int outflank_h = OUTFLANK_2[(OL >> 1) & 0x3f] & PL;
	unsigned long long flipped;

	FLIP_CARRY_2_VEC((unsigned char) FLIPPED_2_H[outflank_h] | ((PL >> 7) & 0x00000200u & OL));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square D1.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_D1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_d;
	unsigned long long flipped, outflank_v;

	outflank_v = ((ULL(OH, OL) | ~0x0808080808080800ULL) + 1) & ULL(PH, PL) & 0x0808080808080800ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0808080808080800ULL;

	outflank_h = OUTFLANK_3[(OL >> 1) & 0x3f] & PL;
	flipped |= (unsigned char) FLIPPED_3_H[outflank_h];

	outflank_d = OUTFLANK_3[((OL & 0x40221400u) * 0x01010101u) >> 25]
		& ((((PH & 0x00000080u) + (PL & 0x41221400u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_3_H[outflank_d] & 0x40221400u;	// A4D1H5

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_D1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask01 = { ~0x0808080808080800ULL, ~0x0000008040201000ULL };
	static const unsigned long long mask2 = ~0x0000000001020400ULL;
	unsigned int outflank_h = OUTFLANK_3[(OL >> 1) & 0x3f] & PL;
	unsigned long long flipped;

	FLIP_CARRY_3_VEC((unsigned int) (unsigned char) FLIPPED_3_H[outflank_h]);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square E1.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_E1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_d;
	unsigned long long flipped, outflank_v;

	outflank_v = ((ULL(OH, OL) | ~0x1010101010101000ULL) + 1) & ULL(PH, PL) & 0x1010101010101000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x1010101010101000ULL;

	outflank_h = OUTFLANK_4[(OL >> 1) & 0x3f] & PL;
	flipped |= (unsigned char) FLIPPED_4_H[outflank_h];

	outflank_d = OUTFLANK_4[((OL & 0x02442800u) * 0x01010101u) >> 25]
		& ((((PH & 0x00000001u) + (PL & 0x82442800u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_4_H[outflank_d] & 0x82442800u;	// A5E1H4

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_E1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask01 = { ~0x1010101010101000ULL, ~0x0000000102040800ULL };
	static const unsigned long long mask2 = ~0x0000000080402000ULL;
	unsigned int outflank_h = OUTFLANK_4[(OL >> 1) & 0x3f] & PL;
	unsigned long long flipped;

	FLIP_CARRY_3_VEC((unsigned int) (unsigned char) FLIPPED_4_H[outflank_h]);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square F1.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_F1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d7;

	outflank_v = ((ULL(OH, OL) | ~0x2020202020202000ULL) + 1) & ULL(PH, PL) & 0x2020202020202000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x2020202020202000ULL;

	outflank_h = OUTFLANK_5[(OL >> 1) & 0x3f] & PL;
	flipped |= (unsigned char) FLIPPED_5_H[outflank_h];

	outflank_d7 = ((ULL(OH, OL) | ~0x0000010204081000ULL) + 1) & ULL(PH, PL) & 0x0000010204080000ULL;
	flipped |= (outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x0000000204081000ULL;

	flipped |= ((PL >> 9) & 0x00004000u & OL);

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_F1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x2020202020202000ULL, ~0x0000010204081000ULL };
	unsigned int outflank_h = OUTFLANK_5[(OL >> 1) & 0x3f] & PL;
	unsigned long long flipped;

	FLIP_CARRY_2_VEC((unsigned char) FLIPPED_5_H[outflank_h] | ((PL >> 9) & 0x00004000u & OL));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square G1.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_G1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d7;

	outflank_v = ((ULL(OH, OL) | ~0x4040404040404000ULL) + 1) & ULL(PH, PL) & 0x4040404040400000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0040404040404000ULL;

	outflank_h = OUTFLANK_7[OL & 0x3e] & (PL << 1);
	flipped |= ((-outflank_h) & 0x3e) << 0;

	outflank_d7 = ((ULL(OH, OL) | ~0x0001020408102000ULL) + 1) & ULL(PH, PL) & 0x0001020408100000ULL;
	flipped |= (outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x0000020408102000ULL;

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_G1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x4040404040404000ULL, ~0x0001020408102000ULL };
	unsigned int outflank_h = OUTFLANK_7[OL & 0x3e] & (PL << 1);
	unsigned long long flipped;

	FLIP_CARRY_2_VEC(((-outflank_h) & 0x3e) << 0);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square H1.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_H1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d7;

	outflank_v = ((ULL(OH, OL) | ~0x8080808080808000ULL) + 1) & ULL(PH, PL) & 0x8080808080800000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0080808080808000ULL;

	outflank_h = OUTFLANK_7[(OL >> 1) & 0x3f] & PL;
	flipped |= ((-outflank_h) & 0x3f) << 1;

	outflank_d7 = ((ULL(OH, OL) | ~0x0102040810204000ULL) + 1) & ULL(PH, PL) & 0x0102040810200000ULL;
	flipped |= (outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x0002040810204000ULL;

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_H1(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x8080808080808000ULL, ~0x0102040810204000ULL };
	unsigned int outflank_h = OUTFLANK_7[(OL >> 1) & 0x3f] & PL;
	unsigned long long flipped;

	FLIP_CARRY_2_VEC(((-outflank_h) & 0x3f) << 1);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square A2.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_A2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d9;

	outflank_v = ((ULL(OH, OL) | ~0x0101010101010000ULL) + 1) & ULL(PH, PL) & 0x0101010101000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0001010101010000ULL;

	outflank_h = ((OL & 0x00007e00u) + 0x00000200u) & PL;
	flipped |= (outflank_h - (outflank_h >> 8)) & 0x00007e00u;

	outflank_d9 = ((ULL(OH, OL) | ~0x4020100804020000ULL) + 1) & ULL(PH, PL) & 0x4020100804000000ULL;
	flipped |= (outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x0020100804020000ULL;

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_A2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x0101010101010000ULL, ~0x4020100804020000ULL };
	unsigned int outflank_h = ((OL & 0x00007e00u) + 0x00000200u) & PL;
	unsigned long long flipped;

	FLIP_CARRY_2_VEC((outflank_h - (outflank_h >> 8)) & 0x00007e00u);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square B2.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_B2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d9;

	outflank_v = ((ULL(OH, OL) | ~0x0202020202020000ULL) + 1) & ULL(PH, PL) & 0x0202020202000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0002020202020000ULL;

	outflank_h = ((OL & 0x00007c00u) + 0x00000400u) & PL;
	flipped |= (outflank_h - (outflank_h >> 8)) & 0x00007c00u;

	outflank_d9 = ((ULL(OH, OL) | ~0x8040201008040000ULL) + 1) & ULL(PH, PL) & 0x8040201008000000ULL;
	flipped |= (outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x0040201008040000ULL;

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_B2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x0202020202020000ULL, ~0x8040201008040000ULL };
	unsigned int outflank_h = ((OL & 0x00007c00u) + 0x00000400u) & PL;
	unsigned long long flipped;

	FLIP_CARRY_2_VEC((outflank_h - (outflank_h >> 8)) & 0x00007c00u);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square C2.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_C2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d9;

	outflank_v = ((ULL(OH, OL) | ~0x0404040404040000ULL) + 1) & ULL(PH, PL) & 0x0404040404000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0004040404040000ULL;

	outflank_h = OUTFLANK_2[(OL >> 9) & 0x3f] & (PL >> 8);
	flipped |= FLIPPED_2_H[outflank_h] & 0x0000ff00u;

	flipped |= ((PL >> 7) & 0x00020000u & OL);

	outflank_d9 = ((ULL(OH, OL) | ~0x0080402010080000ULL) + 1) & ULL(PH, PL) & 0x0080402010080000ULL;
	flipped |= (outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x0000402010080000ULL;

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_C2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x0404040404040000ULL, ~0x0080402010080000ULL };
	unsigned int outflank_h = OUTFLANK_2[(OL >> 9) & 0x3f] & (PL >> 8);
	unsigned long long flipped;

	FLIP_CARRY_2_VEC(((unsigned int) FLIPPED_2_H[outflank_h] & 0x0000ff00u) | ((PL >> 7) & 0x00020000u & OL));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square D2.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_D2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_d;
	unsigned long long flipped, outflank_v;

	outflank_v = ((ULL(OH, OL) | ~0x0808080808080000ULL) + 1) & ULL(PH, PL) & 0x0808080808000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0008080808080000ULL;

	outflank_h = OUTFLANK_3[(OL >> 9) & 0x3f] & (PL >> 8);
	flipped |= FLIPPED_3_H[outflank_h] & 0x0000ff00u;

	outflank_d = OUTFLANK_3[(((OH & 0x00000040u) + (OL & 0x22140000u)) * 0x01010101u) >> 25]
		& ((((PH & 0x00008041u) + (PL & 0x22140000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_3_H[outflank_d] & 0x0000004022140000ULL;	// A5D2H6

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_D2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask01 = { ~0x0808080808080000ULL, ~0x0000804020100000ULL };
	static const unsigned long long mask2 = ~0x0000000102040000ULL;
	unsigned int outflank_h = OUTFLANK_3[(OL >> 9) & 0x3f] & (PL >> 8);
	unsigned long long flipped;

	FLIP_CARRY_3_VEC((unsigned int) FLIPPED_3_H[outflank_h] & 0x0000ff00u);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square E2.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_E2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_d;
	unsigned long long flipped, outflank_v;

	outflank_v = ((ULL(OH, OL) | ~0x1010101010100000ULL) + 1) & ULL(PH, PL) & 0x1010101010000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0010101010100000ULL;

	outflank_h = OUTFLANK_4[(OL >> 9) & 0x3f] & (PL >> 8);
	flipped |= FLIPPED_4_H[outflank_h] & 0x0000ff00u;

	outflank_d = OUTFLANK_4[(((OH & 0x00000002u) + (OL & 0x44280000u)) * 0x01010101u) >> 25]
		& ((((PH & 0x00000182u) + (PL & 0x44280000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_4_H[outflank_d] & 0x0000000244280000ULL;	// A6E2H5

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_E2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask01 = { ~0x1010101010100000ULL, ~0x0000010204080000ULL };
	static const unsigned long long mask2 = ~0x0000008040200000ULL;
	unsigned int outflank_h = OUTFLANK_4[(OL >> 9) & 0x3f] & (PL >> 8);
	unsigned long long flipped;

	FLIP_CARRY_3_VEC((unsigned int) FLIPPED_4_H[outflank_h] & 0x0000ff00u);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square F2.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_F2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d7;

	outflank_v = ((ULL(OH, OL) | ~0x2020202020200000ULL) + 1) & ULL(PH, PL) & 0x2020202020000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0020202020200000ULL;

	outflank_h = OUTFLANK_5[(OL >> 9) & 0x3f] & (PL >> 8);
	flipped |= (unsigned int) FLIPPED_5_H[outflank_h] & 0x0000ff00u;

	outflank_d7 = ((ULL(OH, OL) | ~0x0001020408100000ULL) + 1) & ULL(PH, PL) & 0x0001020408000000ULL;
	flipped |= (outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x0000020408100000ULL;

	flipped |= ((PL >> 9) & 0x00400000u & OL);

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_F2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x2020202020200000ULL, ~0x0001020408100000ULL };
	unsigned int outflank_h = OUTFLANK_5[(OL >> 9) & 0x3f] & (PL >> 8);
	unsigned long long flipped;

	FLIP_CARRY_2_VEC(((unsigned int) FLIPPED_5_H[outflank_h] & 0x0000ff00u) | ((PL >> 9) & 0x00400000u & OL));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square G2.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_G2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d7;

	outflank_v = ((ULL(OH, OL) | ~0x4040404040400000ULL) + 1) & ULL(PH, PL) & 0x4040404040000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0040404040400000ULL;

	outflank_h = OUTFLANK_7[(OL >> 8) & 0x3e] & (PL >> 7);
	flipped |= ((-outflank_h) & 0x3e) << 8;

	outflank_d7 = ((ULL(OH, OL) | ~0x0102040810200000ULL) + 1) & ULL(PH, PL) & 0x0102040810000000ULL;
	flipped |= (outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x0002040810200000ULL;

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_G2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x4040404040400000ULL, ~0x0102040810200000ULL };
	unsigned int outflank_h = OUTFLANK_7[(OL >> 8) & 0x3e] & (PL >> 7);
	unsigned long long flipped;

	FLIP_CARRY_2_VEC(((-outflank_h) & 0x3e) << 8);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square H2.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_H2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d7;

	outflank_v = ((ULL(OH, OL) | ~0x8080808080800000ULL) + 1) & ULL(PH, PL) & 0x8080808080000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0080808080800000ULL;

	outflank_h = OUTFLANK_7[(OL >> 9) & 0x3f] & (PL >> 8);
	flipped |= ((-outflank_h) & 0x3f) << 9;

	outflank_d7 = ((ULL(OH, OL) | ~0x0204081020400000ULL) + 1) & ULL(PH, PL) & 0x0204081020000000ULL;
	flipped |= (outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x0004081020400000ULL;

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_H2(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x8080808080800000ULL, ~0x0204081020400000ULL };
	unsigned int outflank_h = OUTFLANK_7[(OL >> 9) & 0x3f] & (PL >> 8);
	unsigned long long flipped;

	FLIP_CARRY_2_VEC(((-outflank_h) & 0x3f) << 9);

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square A3.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_A3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d9;

	outflank_v = ((ULL(OH, OL) | ~0x0101010101000000ULL) + 1) & ULL(PH, PL) & 0x0101010101000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0101010101000000ULL;

	outflank_h = ((OL & 0x007e0000u) + 0x00020000u) & PL;
	flipped |= (outflank_h - (outflank_h >> 8)) & 0x007e0000u;

	outflank_d9 = ((ULL(OH, OL) | ~0x2010080402000000ULL) + 1) & ULL(PH, PL) & 0x2010080400000000ULL;
	flipped |= (outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x0010080402000000ULL;

	flipped |= OL & (((PL << 8) & 0x00000100u) | ((PL << 7) & 0x00000200u));

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_A3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x0101010101000000ULL, ~0x2010080402000000ULL };
	unsigned int outflank_h = ((OL & 0x007e0000u) + 0x00020000u) & PL;
	unsigned long long flipped;

	FLIP_CARRY_2_VEC(((outflank_h - (outflank_h >> 8)) & 0x007e0000u)
		| (OL & (((PL << 8) & 0x00000100u) | ((PL << 7) & 0x00000200u))));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square B3.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_B3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d9;

	outflank_v = ((ULL(OH, OL) | ~0x0202020202000000ULL) + 1) & ULL(PH, PL) & 0x0202020202000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0202020202000000ULL;

	outflank_h = ((OL & 0x007c0000u) + 0x00040000u) & PL;
	flipped |= (outflank_h - (outflank_h >> 8)) & 0x007c0000u;

	outflank_d9 = ((ULL(OH, OL) | ~0x4020100804000000ULL) + 1) & ULL(PH, PL) & 0x4020100800000000ULL;
	flipped |= (outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x0020100804000000ULL;

	flipped |= OL & (((PL << 8) & 0x00000200u) | ((PL << 7) & 0x00000400u));

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_B3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x0202020202000000ULL, ~0x4020100804000000ULL };
	unsigned int outflank_h = ((OL & 0x007c0000u) + 0x00040000u) & PL;
	unsigned long long flipped;

	FLIP_CARRY_2_VEC(((outflank_h - (outflank_h >> 8)) & 0x007c0000u)
		| (OL & (((PL << 8) & 0x00000200u) | ((PL << 7) & 0x00000400u))));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square C3.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_C3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d9;

	outflank_v = ((ULL(OH, OL) | ~0x0404040404000000ULL) + 1) & ULL(PH, PL) & 0x0404040404000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0404040404000000ULL;

	outflank_h = OUTFLANK_2[(OL >> 17) & 0x3f] & (PL >> 16);
	flipped |= (unsigned int) FLIPPED_2_H[outflank_h] & 0x00ff0000u;

	outflank_d9 = ((ULL(OH, OL) | ~0x8040201008000000ULL) + 1) & ULL(PH, PL) & 0x8040201008000000ULL;
	flipped |= (outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x8040201008000000ULL;

	flipped |= OL & (((PL << 8) & 0x00000400u)
			| ((PL << 9) & 0x00000200u)
			| (((PH << 25) | (PL << 7)) & 0x02000800u));

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_C3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x0404040404000000ULL, ~0x8040201008000000ULL };
	unsigned int outflank_h = OUTFLANK_2[(OL >> 17) & 0x3f] & (PL >> 16);
	unsigned long long flipped;

	FLIP_CARRY_2_VEC(((unsigned int) FLIPPED_2_H[outflank_h] & 0x00ff0000u)
		| (OL & (((PL << 8) & 0x00000400u)
			| ((PL << 9) & 0x00000200u)
			| (((PH << 25) | (PL << 7)) & 0x02000800u))));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square D3.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_D3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_d;
	unsigned long long flipped, outflank_v;

	outflank_v = ((ULL(OH, OL) | ~0x0808080808000000ULL) + 1) & ULL(PH, PL) & 0x0808080808000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x0808080808000000ULL;

	outflank_h = OUTFLANK_3[(OL >> 17) & 0x3f] & (PL >> 16);
	flipped |= (unsigned int) FLIPPED_3_H[outflank_h] & 0x00ff0000u;

	outflank_d = OUTFLANK_3[(((OH & 0x00004022u) + (OL & 0x14080000u)) * 0x01010101u) >> 25]
		& ((((PH & 0x00804122u) + (PL & 0x14080000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_3_H[outflank_d] & 0x0000402214080000ULL;	// A6D3H7

	flipped |= OL & (((PL << 8) & 0x00000800u)
			| ((PL << 7) & 0x00001000u)
			| ((PL << 9) & 0x00000400u));

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_D3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask01 = { ~0x0808080808000000ULL, ~0x0080402010000000ULL };
	static const unsigned long long mask2 = ~0x0000010204000000ULL;
	unsigned int outflank_h = OUTFLANK_3[(OL >> 17) & 0x3f] & (PL >> 16);
	unsigned long long flipped;

	FLIP_CARRY_3_VEC(((unsigned int) FLIPPED_3_H[outflank_h] & 0x00ff0000u)
		| (OL & (((PL << 8) & 0x00000800u)
			| ((PL << 7) & 0x00001000u)
			| ((PL << 9) & 0x00000400u))));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square E3.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_E3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_d;
	unsigned long long flipped, outflank_v;

	outflank_v = ((ULL(OH, OL) | ~0x1010101010000000ULL) + 1) & ULL(PH, PL) & 0x1010101010000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x1010101010000000ULL;

	outflank_h = OUTFLANK_4[(OL >> 17) & 0x3f] & (PL >> 16);
	flipped |= (unsigned int) FLIPPED_4_H[outflank_h] & 0x00ff0000u;

	outflank_d = OUTFLANK_4[(((OH & 0x00000244u) + (OL & 0x28100000u)) * 0x01010101u) >> 25]
		& ((((PH & 0x00018244u) + (PL & 0x28100000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_4_H[outflank_d] & 0x0000024428100000ULL;	// A7E7H6

	flipped |= OL & (((PL << 8) & 0x00001000u)
			| ((PL << 7) & 0x00002000u)
			| ((PL << 9) & 0x00000800u));

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_E3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask01 = { ~0x1010101010000000ULL, ~0x0001020408000000ULL };
	static const unsigned long long mask2 = ~0x0000804020000000ULL;
	unsigned int outflank_h = OUTFLANK_4[(OL >> 17) & 0x3f] & (PL >> 16);
	unsigned long long flipped;

	FLIP_CARRY_3_VEC(((unsigned int) FLIPPED_4_H[outflank_h] & 0x00ff0000u)
		| (OL & (((PL << 8) & 0x00001000u)
			| ((PL << 7) & 0x00002000u)
			| ((PL << 9) & 0x00000800u))));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square F3.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_F3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d7;

	outflank_v = ((ULL(OH, OL) | ~0x2020202020000000ULL) + 1) & ULL(PH, PL) & 0x2020202020000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x2020202020000000ULL;

	outflank_h = OUTFLANK_5[(OL >> 17) & 0x3f] & (PL >> 16);
	flipped |= (unsigned int) FLIPPED_5_H[outflank_h] & 0x00ff0000u;

	outflank_d7 = ((ULL(OH, OL) | ~0x0102040810000000ULL) + 1) & ULL(PH, PL) & 0x0102040810000000ULL;
	flipped |= (outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x0102040810000000ULL;

	flipped |= OL & (((PL << 8) & 0x00002000u)
			| ((PL << 7) & 0x00004000u)
			| (((PH << 23) | (PL << 9)) & 0x40001000u));

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_F3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x2020202020000000ULL, ~0x0102040810000000ULL };
	unsigned int outflank_h = OUTFLANK_5[(OL >> 17) & 0x3f] & (PL >> 16);
	unsigned long long flipped;

	FLIP_CARRY_2_VEC(((unsigned int) FLIPPED_5_H[outflank_h] & 0x00ff0000u)
		| (OL & (((PL << 8) & 0x00002000u)
			| ((PL << 7) & 0x00004000u)
			| (((PH << 23) | (PL << 9)) & 0x40001000u))));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square G3.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_G3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d7;

	outflank_v = ((ULL(OH, OL) | ~0x4040404040000000ULL) + 1) & ULL(PH, PL) & 0x4040404040000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x4040404040000000ULL;

	outflank_h = OUTFLANK_7[(OL >> 16) & 0x3e] & (PL >> 15);
	flipped |= ((-outflank_h) & 0x3e) << 16;

	outflank_d7 = ((ULL(OH, OL) | ~0x0204081020000000ULL) + 1) & ULL(PH, PL) & 0x0204081000000000ULL;
	flipped |= (outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x0004081020000000ULL;

	flipped |= OL & (((PL << 8) & 0x00004000u) | ((PL << 9) & 0x00002000u));

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_G3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x4040404040000000ULL, ~0x0204081020000000ULL };
	unsigned int outflank_h = OUTFLANK_7[(OL >> 16) & 0x3e] & (PL >> 15);
	unsigned long long flipped;

	FLIP_CARRY_2_VEC((((-outflank_h) & 0x3e) << 16)
		| (OL & (((PL << 8) & 0x00004000u) | ((PL << 9) & 0x00002000u))));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square H3.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
#ifndef hasSSE2
static unsigned long long flip_H3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h;
	unsigned long long flipped, outflank_v, outflank_d7;

	outflank_v = ((ULL(OH, OL) | ~0x8080808080000000ULL) + 1) & ULL(PH, PL) & 0x8080808080000000ULL;
	flipped = (outflank_v - (unsigned int) (outflank_v != 0)) & 0x8080808080000000ULL;

	outflank_h = OUTFLANK_7[(OL >> 17) & 0x3f] & (PL >> 16);
	flipped |= ((-outflank_h) & 0x3f) << 17;

	outflank_d7 = ((ULL(OH, OL) | ~0x0408102040000000ULL) + 1) & ULL(PH, PL) & 0x0408102000000000ULL;
	flipped |= (outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x0008102040000000ULL;

	flipped |= OL & (((PL << 8) & 0x00008000u) | ((PL << 9) & 0x00004000u));

	return flipped;
}
#endif
#ifdef USE_GAS_MMX
static unsigned long long SSE2 flip_sse_H3(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	static const __v2di mask = { ~0x8080808080000000ULL, ~0x0408102040000000ULL };
	unsigned int outflank_h = OUTFLANK_7[(OL >> 17) & 0x3f] & (PL >> 16);
	unsigned long long flipped;

	FLIP_CARRY_2_VEC((((-outflank_h) & 0x3f) << 17)
		| (OL & (((PL << 8) & 0x00008000u) | ((PL << 9) & 0x00004000u))));

	return flipped;
}
#endif

/**
 * Compute flipped discs when playing on square A4.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_A4(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, flip_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_3[(((OL & 0x01010100u) + ((OH & 0x00010101u) << 4)) * 0x01020408u) >> 25]
		& ((((PL & 0x01010101u) + ((PH & 0x01010101u) << 4)) * 0x01020408u) >> 24);
	flipped = FLIPPED_3_V[outflank_v] & 0x0001010101010100ULL;

	outflank_h = ((OL & 0x7e000000u) + 0x02000000u) & PL;
	flipped |= (outflank_h - (outflank_h >> 8)) & 0x7e000000u;

	flip_d7 = OL & 0x00020000u;
	flip_d7 |= (flip_d7 >> 7) & OL;
	flipped |= flip_d7 & -(flip_d7 & (PL << 7));

	outflank_d9 = ((OH | ~0x10080402u) + 0x00000002u) & PH & 0x10080400u;
	flipped |= (unsigned long long) ((outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x00080402u) << 32;

	return flipped;
}

/**
 * Compute flipped discs when playing on square B4.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_B4(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, flip_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_3[(((OL & 0x02020200u) + ((OH & 0x00020202u) << 4)) * 0x00810204u) >> 25]
		& ((((PL & 0x02020202u) + ((PH & 0x02020202u) << 4)) * 0x00810204u) >> 24);
	flipped = FLIPPED_3_V[outflank_v] & 0x0002020202020200ULL;

	outflank_h = ((OL & 0x7c000000u) + 0x04000000u) & PL;
	flipped |= (outflank_h - (outflank_h >> 8)) & 0x7c000000u;

	flip_d7 = OL & 0x00040000u;
	flip_d7 |= (flip_d7 >> 7) & OL;
	flipped |= flip_d7 & -(flip_d7 & (PL << 7));

	outflank_d9 = ((OH | ~0x20100804u) + 0x00000004u) & PH & 0x20100800u;
	flipped |= (unsigned long long) ((outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x00100804u) << 32;

	return flipped;
}

/**
 * Compute flipped discs when playing on square C4.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */

#if 0 // MMX - slower

static unsigned long long flip_C4(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_3[(((OL & 0x04040400u) + ((OH & 0x00040404u) << 4)) * 0x00408102u) >> 25]
		& ((((PL & 0x04040404u) + ((PH & 0x04040404u) << 4)) * 0x00408102u) >> 24);
	__asm__ volatile (
		"movq	%0, %%mm0\n\t"
		"pand	%1, %%mm0"
	:: "m" (FLIPPED_3_V[outflank_v]), "m" (mask_c1c8));

	outflank_h = OUTFLANK_2[(OL >> 25) & 0x3f] & (PL >> 24);
	__asm__ volatile (
		"movq	%0, %%mm1\n\t"
		"pand	%1, %%mm1\n\t"
		"por	%%mm1, %%mm0"
	:: "m" (FLIPPED_2_H[outflank_h]), "m" (mask_a4h4));

	outflank_d7 = OUTFLANK_2[(((OL & 0x04081000u) + (OH & 0x00000002u)) * 0x01010101u) >> 25]
		& ((((PL & 0x04081020u) + (PH & 0x00000102u)) * 0x01010101u) >> 24);
	__asm__ volatile (
		"movq	%0, %%mm1\n\t"
		"pand	%1, %%mm1\n\t"
		"por	%%mm1, %%mm0"
	:: "m" (FLIPPED_2_H[outflank_d7]), "m" (mask_f1a6));

	outflank_d9 = OUTFLANK_2[(((OL & 0x04020000u) + (OH & 0x00201008u)) * 0x01010101u) >> 25]
		& ((((PL & 0x04020100u) + (PH & 0x40201008u)) * 0x01010101u) >> 24);
	__asm__ volatile (
		"movq	%1, %%mm1\n\t"
		"pand	%2, %%mm1\n\t"
		"por	%%mm1, %%mm0\n\t"
		"movd	%%mm0, %%eax\n\t"
		"psrlq	$32, %%mm0\n\t"
		"movd	%%mm0, %%edx\n\t"
		"emms"
	: "=A" (flipped) : "m" (FLIPPED_2_H[outflank_d9]), "m" (mask_a2g8));

	return flipped;
}

#elif 0 // SSE2 - even slow

static unsigned long long flip_C4(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, outflank_d9;
	__v2di flipped;

	outflank_v = OUTFLANK_3[(((OL & 0x04040400u) + ((OH & 0x00040404u) << 4)) * 0x00408102u) >> 25]
		& ((((PL & 0x04040404u) + ((PH & 0x04040404u) << 4)) * 0x00408102u) >> 24);
	outflank_h = OUTFLANK_2[(OL >> 25) & 0x3f] & (PL >> 24);
	flipped = _mm_set_epi64x(FLIPPED_2_H[outflank_h], FLIPPED_3_V[outflank_v])
		& _mm_set_epi64x(mask_a4h4, mask_c1c8);

	outflank_d7 = OUTFLANK_2[(((OL & 0x04081000u) + (OH & 0x00000002u)) * 0x01010101u) >> 25]
		& ((((PL & 0x04081020u) + (PH & 0x00000102u)) * 0x01010101u) >> 24);
	outflank_d9 = OUTFLANK_2[(((OL & 0x04020000u) + (OH & 0x00201008u)) * 0x01010101u) >> 25]
		& ((((PL & 0x04020100u) + (PH & 0x40201008u)) * 0x01010101u) >> 24);
	flipped |= _mm_set_epi64x(FLIPPED_2_H[outflank_d9], FLIPPED_2_H[outflank_d7])
		& _mm_set_epi64x(mask_a2g8, mask_f1a6);

	flipped |= _mm_shuffle_epi32(flipped, 0x4e);
	return (unsigned long long) _mm_movepi64_pi64(flipped);	// flipped[0]
}

#else

static unsigned long long flip_C4(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_3[(((OL & 0x04040400u) + ((OH & 0x00040404u) << 4)) * 0x00408102u) >> 25]
		& ((((PL & 0x04040404u) + ((PH & 0x04040404u) << 4)) * 0x00408102u) >> 24);
	flipped = FLIPPED_3_V[outflank_v] & 0x0004040404040400ULL;

	outflank_h = OUTFLANK_2[(OL >> 25) & 0x3f] & (PL >> 24);
	flipped |= (unsigned int) FLIPPED_2_H[outflank_h] & 0xff000000u;

	outflank_d7 = OUTFLANK_2[(((OL & 0x04081000u) + (OH & 0x00000002u)) * 0x01010101u) >> 25]
		& ((((PL & 0x04081020u) + (PH & 0x00000102u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_2_H[outflank_d7] & 0x0000000204081000ULL;

	outflank_d9 = OUTFLANK_2[(((OL & 0x04020000u) + (OH & 0x00201008u)) * 0x01010101u) >> 25]
		& ((((PL & 0x04020100u) + (PH & 0x40201008u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_2_H[outflank_d9] & 0x0020100804020000ULL;

	return flipped;
}

#endif

/**
 * Compute flipped discs when playing on square D4.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_D4(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_3[(((OL & 0x08080800u) + ((OH & 0x00080808u) << 4)) * 0x00204081u) >> 25]
		& ((((PL & 0x08080808u) + ((PH & 0x08080808u) << 4)) * 0x00204081u) >> 24);
	flipped = FLIPPED_3_V[outflank_v] & 0x0008080808080800ULL;

	outflank_h = OUTFLANK_3[(OL >> 25) & 0x3f] & (PL >> 24);
	flipped |= (unsigned int) FLIPPED_3_H[outflank_h] & 0xff000000u;

	outflank_d7 = OUTFLANK_3[(((OL & 0x08102000u) + (OH & 0x00000204u)) * 0x01010101u) >> 25]
		& ((((PL & 0x08102040u) + (PH & 0x00010204u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_3_H[outflank_d7] & 0x0000020408102000ULL;

	outflank_d9 = OUTFLANK_3[(((OL & 0x08040200u) + (OH & 0x00402010u)) * 0x01010101u) >> 25]
		& ((((PL & 0x08040201u) + (PH & 0x80402010u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_3_H[outflank_d9] & 0x0040201008040200ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square E3.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_E4(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_3[((((OL & 0x10101000u) >> 4) + (OH & 0x00101010u)) * 0x01020408u) >> 25]
		& (((((PL & 0x10101010u) >> 4) + (PH & 0x10101010u)) * 0x01020408u) >> 24);
	flipped = FLIPPED_3_V[outflank_v] & 0x0010101010101000ULL;

	outflank_h = OUTFLANK_4[(OL >> 25) & 0x3f] & (PL >> 24);
	flipped |= (unsigned int) FLIPPED_4_H[outflank_h] & 0xff000000u;

	outflank_d7 = OUTFLANK_4[(((OL & 0x10204000u) + (OH & 0x00020408u)) * 0x01010101u) >> 25]
		& ((((PL & 0x10204080u) + (PH & 0x01020408u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_4_H[outflank_d7] & 0x0002040810204000ULL;

	outflank_d9 = OUTFLANK_4[(((OL & 0x10080400u) + (OH & 0x00004020u)) * 0x01010101u) >> 25]
		& ((((PL & 0x10080402u) + (PH & 0x00804020u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_4_H[outflank_d9] & 0x0000402010080400ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square F4.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_F4(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_3[((((OL & 0x20202000u) >> 4) + (OH & 0x00202020u)) * 0x00810204u) >> 25]
		& (((((PL & 0x20202020u) >> 4) + (PH & 0x20202020u)) * 0x00810204u) >> 24);
	flipped = FLIPPED_3_V[outflank_v] & 0x0020202020202000ULL;

	outflank_h = OUTFLANK_5[(OL >> 25) & 0x3f] & (PL >> 24);
	flipped |= (unsigned int) FLIPPED_5_H[outflank_h] & 0xff000000u;

	outflank_d7 = OUTFLANK_5[(((OL & 0x20400000u) + (OH & 0x00040810u)) * 0x01010101u) >> 25]
		& ((((PL & 0x20408000u) + (PH & 0x02040810u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_5_H[outflank_d7] & 0x0004081020400000ULL;

	outflank_d9 = OUTFLANK_5[(((OL & 0x20100800u) + (OH & 0x00000040u)) * 0x01010101u) >> 25]
		& ((((PL & 0x20100804u) + (PH & 0x00008040u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_5_H[outflank_d9] & 0x0000004020100800ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square G4.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_G4(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, flip_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_3[((((OL & 0x40404000u) >> 4) + (OH & 0x00404040u)) * 0x00408102u) >> 25]
		& (((((PL & 0x40404040u) >> 4) + (PH & 0x40404040u)) * 0x00408102u) >> 24);
	flipped = FLIPPED_3_V[outflank_v] & 0x0040404040404000ULL;

	outflank_h = OUTFLANK_7[(OL >> 24) & 0x3e] & (PL >> 23);
	flipped |= ((-outflank_h) & 0x3e) << 24;

	outflank_d7 = ((OH | ~0x04081020u) + 0x00000020u) & PH & 0x04081000u;
	flipped |= (unsigned long long) ((outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x00081020u) << 32;

	flip_d9 = OL & 0x00200000u;
	flip_d9 |= (flip_d9 >> 9) & OL;
	flipped |= flip_d9 & -(flip_d9 & (PL << 9));

	return flipped;
}

/**
 * Compute flipped discs when playing on square H4.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_H4(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, flip_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_3[((((OL & 0x80808000u) >> 4) + (OH & 0x00808080u)) * 0x00204081u) >> 25]
		& (((((PL & 0x80808080u) >> 4) + (PH & 0x80808080u)) * 0x00204081u) >> 24);
	flipped = FLIPPED_3_V[outflank_v] & 0x0080808080808000ULL;

	outflank_h = OUTFLANK_7[(OL >> 25) & 0x3f] & (PL >> 24);
	flipped |= ((-outflank_h) & 0x3f) << 25;

	outflank_d7 = ((OH | ~0x08102040u) + 0x00000040u) & PH & 0x08102000u;
	flipped |= (unsigned long long) ((outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x00102040u) << 32;

	flip_d9 = OL & 0x00400000u;
	flip_d9 |= (flip_d9 >> 9) & OL;
	flipped |= flip_d9 & -(flip_d9 & (PL << 9));

	return flipped;
}

/**
 * Compute flipped discs when playing on square A5.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_A5(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, flip_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_4[(((OL & 0x01010100u) + ((OH & 0x00010101u) << 4)) * 0x01020408u) >> 25]
		& ((((PL & 0x01010101u) + ((PH & 0x01010101u) << 4)) * 0x01020408u) >> 24);
	flipped = FLIPPED_4_V[outflank_v] & 0x0001010101010100ULL;

	outflank_h = ((OH & 0x0000007eu) + 0x00000002u) & PH;
	flipped |= (unsigned long long) ((((outflank_h << 8) - outflank_h) >> 8) & 0x0000007eu) << 32;

	flip_d7 = OL & ((OL >> 7) | 0x02000000u);
	flip_d7 &= ((flip_d7 & 0x02040000u) >> 14) | 0x02040000u;
	flipped |= flip_d7 & -(flip_d7 & (PL << 7));

	outflank_d9 = ((OH | ~0x08040200u) + 0x00000200u) & PH & 0x08040000u;
	flipped |= (unsigned long long) ((outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x00040200u) << 32;

	return flipped;
}

/**
 * Compute flipped discs when playing on square B5.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_B5(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, flip_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_4[(((OL & 0x02020200u) + ((OH & 0x00020202u) << 4)) * 0x00810204u) >> 25]
		& ((((PL & 0x02020202u) + ((PH & 0x02020202u) << 4)) * 0x00810204u) >> 24);
	flipped = FLIPPED_4_V[outflank_v] & 0x0002020202020200ULL;

	outflank_h = ((OH & 0x0000007cu) + 0x00000004u) & (PH >> 0);
	flipped |= (unsigned long long) ((((outflank_h << 8) - outflank_h) >> 8) & 0x0000007cu) << 32;

	flip_d7 = OL & ((OL >> 7) | 0x04000000u);
	flip_d7 &= ((flip_d7 & 0x04080000u) >> 14) | 0x04080000u;
	flipped |= flip_d7 & -(flip_d7 & (PL << 7));

	outflank_d9 = ((OH | ~0x10080400u) + 0x00000400u) & PH & 0x10080000u;
	flipped |= (unsigned long long) ((outflank_d9 - (unsigned int) (outflank_d9 != 0)) & 0x00080400u) << 32;

	return flipped;
}

/**
 * Compute flipped discs when playing on square C5.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_C5(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_4[(((OL & 0x04040400u) + ((OH & 0x00040404u) << 4)) * 0x00408102u) >> 25]
		& ((((PL & 0x04040404u) + ((PH & 0x04040404u) << 4)) * 0x00408102u) >> 24);
	flipped = FLIPPED_4_V[outflank_v] & 0x0004040404040400ULL;

	outflank_h = OUTFLANK_2[(OH >> 1) & 0x3f] & (PH >> 0);
	flipped |= FLIPPED_2_H[outflank_h] & 0x000000ff00000000ULL;

	outflank_d7 = OUTFLANK_2[(((OL & 0x08102000u) + (OH & 0x00000204u)) * 0x01010101u) >> 25]
		& ((((PL & 0x08102040u) + (PH & 0x00010204u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_2_H[outflank_d7] & 0x0000020408102000ULL;

	outflank_d9 = OUTFLANK_2[(((OL & 0x02000000u) + (OH & 0x00100804u)) * 0x01010101u) >> 25]
		& ((((PL & 0x02010000u) + (PH & 0x20100804u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_2_H[outflank_d9] & 0x0010080402000000ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square D5.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_D5(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_4[(((OL & 0x08080800u) + ((OH & 0x00080808u) << 4)) * 0x00204081u) >> 25]
		& ((((PL & 0x08080808u) + ((PH & 0x08080808u) << 4)) * 0x00204081u) >> 24);
	flipped = FLIPPED_4_V[outflank_v] & 0x0008080808080800ULL;

	outflank_h = OUTFLANK_3[(OH >> 1) & 0x3f] & (PH >> 0);
	flipped |= FLIPPED_3_H[outflank_h] & 0x000000ff00000000ULL;

	outflank_d7 = OUTFLANK_3[(((OL & 0x10204000u) + (OH & 0x00020408u)) * 0x01010101u) >> 25]
		& ((((PL & 0x10204080u) + (PH & 0x01020408u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_3_H[outflank_d7] & 0x0002040810204000ULL;

	outflank_d9 = OUTFLANK_3[(((OL & 0x04020000u) + (OH & 0x00201008u)) * 0x01010101u) >> 25]
		& ((((PL & 0x04020100u) + (PH & 0x40201008u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_3_H[outflank_d9] & 0x0020100804020000ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square E5.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_E5(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_4[((((OL & 0x10101000u) >> 4) + (OH & 0x00101010u)) * 0x01020408u) >> 25]
		& (((((PL & 0x10101010u) >> 4) + (PH & 0x10101010u)) * 0x01020408u) >> 24);
	flipped = FLIPPED_4_V[outflank_v] & 0x0010101010101000ULL;

	outflank_h = OUTFLANK_4[(OH >> 1) & 0x3f] & (PH >> 0);
	flipped |= FLIPPED_4_H[outflank_h] & 0x000000ff00000000ULL;

	outflank_d7 = OUTFLANK_4[(((OL & 0x20400000u) + (OH & 0x00040810u)) * 0x01010101u) >> 25]
		& ((((PL & 0x20408000u) + (PH & 0x02040810u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_4_H[outflank_d7] & 0x0004081020400000ULL;

	outflank_d9 = OUTFLANK_4[(((OL & 0x08040200u) + (OH & 0x00402010u)) * 0x01010101u) >> 25]
		& ((((PL & 0x08040201u) + (PH & 0x80402010u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_4_H[outflank_d9] & 0x0040201008040200ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square F5.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_F5(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_4[((((OL & 0x20202000u) >> 4) + (OH & 0x00202020u)) * 0x00810204u) >> 25]
		& (((((PL & 0x20202020u) >> 4) + (PH & 0x20202020u)) * 0x00810204u) >> 24);
	flipped = FLIPPED_4_V[outflank_v] & 0x0020202020202000ULL;

	outflank_h = OUTFLANK_5[(OH >> 1) & 0x3f] & (PH >> 0);
	flipped |= FLIPPED_5_H[outflank_h] & 0x000000ff00000000ULL;

	outflank_d7 = OUTFLANK_5[(((OL & 0x40000000u) + (OH & 0x00081020u)) * 0x01010101u) >> 25]
		& ((((PL & 0x40800000u) + (PH & 0x04081020u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_5_H[outflank_d7] & 0x0008102040000000ULL;

	outflank_d9 = OUTFLANK_5[(((OL & 0x10080400u) + (OH & 0x00004020u)) * 0x01010101u) >> 25]
		& ((((PL & 0x10080402u) + (PH & 0x00804020u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_5_H[outflank_d9] & 0x0000402010080400ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square G5.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_G5(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, flip_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_4[((((OL & 0x40404000u) >> 4) + (OH & 0x00404040u)) * 0x00408102u) >> 25]
		& (((((PL & 0x40404040u) >> 4) + (PH & 0x40404040u)) * 0x00408102u) >> 24);
	flipped = FLIPPED_4_V[outflank_v] & 0x0040404040404000ULL;

	outflank_h = OUTFLANK_7[(OH >> 0) & 0x3e] & (PH << 1);
	flipped |= (unsigned long long) ((-outflank_h) & 0x3e) << 32;

	outflank_d7 = ((OH | ~0x08102000u) + 0x00002000u) & PH & 0x08100000u;
	flipped |= (unsigned long long) ((outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x00102000u) << 32;

	flip_d9 = OL & ((OL >> 9) | 0x20000000u);
	flip_d9 &= ((flip_d9 & 0x20100000u) >> 18) | 0x20100000u;
	flipped |= flip_d9 & -(flip_d9 & (PL << 9));

	return flipped;
}

/**
 * Compute flipped discs when playing on square H5.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_H5(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7, flip_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_4[((((OL & 0x80808000u) >> 4) + (OH & 0x00808080u)) * 0x00204081u) >> 25]
		& (((((PL & 0x80808080u) >> 4) + (PH & 0x80808080u)) * 0x00204081u) >> 24);
	flipped = FLIPPED_4_V[outflank_v] & 0x0080808080808000ULL;

	outflank_h = OUTFLANK_7[(OH >> 1) & 0x3f] & (PH >> 0);
	flipped |= (unsigned long long) ((-outflank_h) & 0x3f) << 33;

	outflank_d7 = ((OH | ~0x10204000u) + 0x00004000u) & PH & 0x10200000u;
	flipped |= (unsigned long long) ((outflank_d7 - (unsigned int) (outflank_d7 != 0)) & 0x00204000u) << 32;

	flip_d9 = OL & ((OL >> 9) | 0x40000000u);
	flip_d9 &= ((flip_d9 & 0x40200000u) >> 18) | 0x40200000u;
	flipped |= flip_d9 & -(flip_d9 & (PL << 9));

	return flipped;
}

/**
 * Compute flipped discs when playing on square A6.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_A6(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, flip_d7;
	unsigned long long flipped;

	outflank_v = OUTFLANK_5[(((OL & 0x01010100u) + ((OH & 0x00010101u) << 4)) * 0x01020408u) >> 25]
		& ((((PL & 0x01010101u) + ((PH & 0x01010101u) << 4)) * 0x01020408u) >> 24);
	flipped = FLIPPED_5_V[outflank_v] & 0x0001010101010100ULL;

	outflank_h = ((OH & 0x00007e00u) + 0x00000200u) & PH;
	flipped |= (unsigned long long) ((outflank_h - (outflank_h >> 8)) & 0x00007e00u) << 32;

	flip_d7 = (OL >> 8) | (OH << 24);
	flip_d7 &= (flip_d7 >> 7) | 0x02000000u;
	flip_d7 &= ((flip_d7 & 0x02040000u) >> 14) | 0x02040000u;
	flipped |= (unsigned long long) (flip_d7 & -(flip_d7 & (PL >> 1))) << 8;

	flipped |= (unsigned long long) ((PH >> 9) & 0x00020000u & OH) << 32;

	return flipped;
}

/**
 * Compute flipped discs when playing on square B6.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_B6(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, flip_d7;
	unsigned long long flipped;

	outflank_v = OUTFLANK_5[(((OL & 0x02020200u) + ((OH & 0x00020202u) << 4)) * 0x00810204u) >> 25]
		& ((((PL & 0x02020202u) + ((PH & 0x02020202u) << 4)) * 0x00810204u) >> 24);
	flipped = FLIPPED_5_V[outflank_v] & 0x0002020202020200ULL;

	outflank_h = ((OH & 0x00007c00u) + 0x00000400u) & PH;
	flipped |= (unsigned long long) ((outflank_h - (outflank_h >> 8)) & 0x00007c00u) << 32;

	flip_d7 = (OL >> 8) | (OH << 24);
	flip_d7 &= (flip_d7 >> 7) | 0x04000000u;
	flip_d7 &= ((flip_d7 & 0x04080000u) >> 14) | 0x04080000u;
	flipped |= (unsigned long long) (flip_d7 & -(flip_d7 & (PL >> 1))) << 8;

	flipped |= (unsigned long long) ((PH >> 9) & 0x00040000u & OH) << 32;

	return flipped;
}

/**
 * Compute flipped discs when playing on square C6.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_C6(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7;
	unsigned long long flipped;

	outflank_v = OUTFLANK_5[(((OL & 0x04040400u) + ((OH & 0x00040404u) << 4)) * 0x00408102u) >> 25]
		& ((((PL & 0x04040404u) + ((PH & 0x04040404u) << 4)) * 0x00408102u) >> 24);
	flipped = FLIPPED_5_V[outflank_v] & 0x0004040404040400ULL;

	outflank_h = OUTFLANK_2[(OH >> 9) & 0x3f] & (PH >> 8);
	flipped |= FLIPPED_2_H[outflank_h] & 0x0000ff0000000000ULL;

	outflank_d7 = OUTFLANK_2[(((OL & 0x10204000u) + (OH & 0x00020408u)) * 0x01010101u) >> 25]
		& ((((PL & 0x10204080u) + (PH & 0x01020408u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_2_H[outflank_d7] & 0x0002040810204000ULL;

	flipped |= (unsigned long long) (((PH >> 9) | (PL >> 23)) & 0x00080002u & OH) << 32;

	return flipped;
}

/**
 * Compute flipped discs when playing on square D6.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_D6(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d;
	unsigned long long flipped;

	outflank_v = OUTFLANK_5[(((OL & 0x08080800u) + ((OH & 0x00080808u) << 4)) * 0x00204081u) >> 25]
		& ((((PL & 0x08080808u) + ((PH & 0x08080808u) << 4)) * 0x00204081u) >> 24);
	flipped = FLIPPED_5_V[outflank_v] & 0x0008080808080800ULL;

	outflank_h = OUTFLANK_3[(OH >> 9) & 0x3f] & (PH >> 8);
	flipped |= FLIPPED_3_H[outflank_h] & 0x0000ff0000000000ULL;

	outflank_d = OUTFLANK_3[(((OL & 0x22400000u) + (OH & 0x00000814u)) * 0x01010101u) >> 25]
		& ((((PL & 0x22418000u) + (PH & 0x00000814u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_3_H[outflank_d] & 0x0000081422400000ULL;	// A3D6H2

	flipped |= (unsigned long long) (OH &
		(((PH >> 9) & 0x00100000u) | ((PH >> 7) & 0x00040000u))) << 32;

	return flipped;
}

/**
 * Compute flipped discs when playing on square E6.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_E6(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d;
	unsigned long long flipped;

	outflank_v = OUTFLANK_5[((((OL & 0x10101000u) >> 4) + (OH & 0x00101010u)) * 0x01020408u) >> 25]
		& (((((PL & 0x10101010u) >> 4) + (PH & 0x10101010u)) * 0x01020408u) >> 24);
	flipped = FLIPPED_5_V[outflank_v] & 0x0010101010101000ULL;

	outflank_h = OUTFLANK_4[(OH >> 9) & 0x3f] & (PH >> 8);
	flipped |= FLIPPED_4_H[outflank_h] & 0x0000ff0000000000ULL;

	outflank_d = OUTFLANK_4[(((OL & 0x44020000u) + (OH & 0x00001028u)) * 0x01010101u) >> 25]
		& ((((PL & 0x44820100u) + (PH & 0x00001028u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_4_H[outflank_d] & 0x0000102844020000ULL;	// A2E6H3

	flipped |= (unsigned long long) (OH &
		(((PH >> 9) & 0x00200000u) | ((PH >> 7) & 0x00080000u))) << 32;

	return flipped;
}

/**
 * Compute flipped discs when playing on square F6.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_F6(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_5[((((OL & 0x20202000u) >> 4) + (OH & 0x00202020u)) * 0x00810204u) >> 25]
		& (((((PL & 0x20202020u) >> 4) + (PH & 0x20202020u)) * 0x00810204u) >> 24);
	flipped = FLIPPED_5_V[outflank_v] & 0x0020202020202000ULL;

	outflank_h = OUTFLANK_5[(OH >> 9) & 0x3f] & (PH >> 8);
	flipped |= FLIPPED_5_H[outflank_h] & 0x0000ff0000000000ULL;

	flipped |= (unsigned long long) (((PH >> 7) | (PL >> 25)) & 0x00100040u & OH) << 32;

	outflank_d9 = OUTFLANK_5[(((OL & 0x08040200u) + (OH & 0x00402010u)) * 0x01010101u) >> 25]
		& ((((PL & 0x08040201u) + (PH & 0x80402010u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_5_H[outflank_d9] & 0x0040201008040200ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square G6.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_G6(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, flip_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_5[((((OL & 0x40404000u) >> 4) + (OH & 0x00404040u)) * 0x00408102u) >> 25]
		& (((((PL & 0x40404040u) >> 4) + (PH & 0x40404040u)) * 0x00408102u) >> 24);
	flipped = FLIPPED_5_V[outflank_v] & 0x0040404040404000ULL;

	outflank_h = OUTFLANK_7[(OH >> 8) & 0x3e] & (PH >> 7);
	flipped |= (unsigned long long) ((-outflank_h) & 0x3e) << 40;

	flipped |= (unsigned long long) ((PH >> 7) & 0x00200000u & OH) << 32;

	flip_d9 = (OL >> 8) | (OH << 24);
	flip_d9 &= (flip_d9 >> 9) | 0x20000000u;
	flip_d9 &= ((flip_d9 & 0x20100000u) >> 18) | 0x20100000u;
	flipped |= (unsigned long long) (flip_d9 & -(flip_d9 & (PL << 1))) << 8;

	return flipped;
}

/**
 * Compute flipped discs when playing on square H6.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_H6(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, flip_d9;
	unsigned long long flipped;

	outflank_v = OUTFLANK_5[((((OL & 0x80808000u) >> 4) + (OH & 0x00808080u)) * 0x00204081u) >> 25]
		& (((((PL & 0x80808080u) >> 4) + (PH & 0x80808080u)) * 0x00204081u) >> 24);
	flipped = FLIPPED_5_V[outflank_v] & 0x0080808080808000ULL;

	outflank_h = OUTFLANK_7[(OH >> 9) & 0x3f] & (PH >> 8);
	flipped |= (unsigned long long) ((-outflank_h) & 0x3f) << 41;

	flipped |= (unsigned long long) ((PH >> 7) & 0x00400000u & OH) << 32;

	flip_d9 = (OL >> 8) | (OH << 24);
	flip_d9 &= (flip_d9 >> 9) | 0x40000000u;
	flip_d9 &= ((flip_d9 & 0x40200000u) >> 18) | 0x40200000u;
	flipped |= (unsigned long long) (flip_d9 & -(flip_d9 & (PL << 1))) << 8;

	return flipped;
}

/**
 * Compute flipped discs when playing on square A7.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_A7(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x01010100u) << 4) + (OH & 0x00000101u)) * 0x08040201u + 0x04000000u)
		& (((PL & 0x01010101u) << 4) + (PH & 0x00000001u)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x0000003e1e0e0602ULL) & 0x0000010101010100ULL;

	outflank_h = ((OH & 0x007e0000u) + 0x00020000u) & PH;
	flipped |= (unsigned long long) ((outflank_h - (outflank_h >> 8)) & 0x007e0000u) << 32;

	outflank_d7 = (((((OL & 0x08102000u) + (OH & 0x00000204u)) * 0x01010101u) >> 24) + 2)
		& ((((PL & 0x08102040u) + (PH & 0x00000004u)) * 0x01010101u) >> 24);
	flipped |= (outflank_d7 * 0x000000f8f0e0c080ULL) & 0x0000020408102000ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square B7.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_B7(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d7;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x02020200u) << 3) + ((OH & 0x00000202u) >> 1)) * 0x08040201u + 0x04000000u)
		& (((PL & 0x02020202u) << 3) + ((PH & 0x00000002u) >> 1)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x0000007c3c1c0c04ULL) & 0x0000020202020200ULL;

	outflank_h = ((OH & 0x007c0000u) + 0x00040000u) & PH;
	flipped |= (unsigned long long) ((outflank_h - (outflank_h >> 8)) & 0x007c0000u) << 32;

	outflank_d7 = ((((OL & 0x10204000u) + (OH & 0x00000408u)) * 0x01010101u + 0x04000000u)
		& ((PL & 0x10204080u) + (PH & 0x00000008u)) * 0x01010101u) >> 25;
	flipped |= (outflank_d7 * 0x000001f1e1c18100ULL) & 0x0000040810204000ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square C7.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_C7(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x04040400u) << 2) + ((OH & 0x00000404u) >> 2)) * 0x08040201u + 0x04000000u)
		& (((PL & 0x04040404u) << 2) + ((PH & 0x00000004u) >> 2)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x000000f878381808ULL) & 0x0000040404040400ULL;

	outflank_h = OUTFLANK_2[(OH >> 17) & 0x3f] & (PH >> 16);
	flipped |= FLIPPED_2_H[outflank_h] & 0x00ff000000000000ULL;

	outflank_d = OUTFLANK_2[(((OH & 0x00040a10u) + (OL & 0x20400000u)) * 0x01010101u) >> 25]
		& ((((PH & 0x00040a11u) + (PL & 0x20408000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_2_H[outflank_d] & 0x00040a1020400000ULL;	// A5C7H2

	return flipped;
}

/**
 * Compute flipped discs when playing on square D7.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_D7(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x08080800u) << 1) + ((OH & 0x00000808u) >> 3)) * 0x08040201u + 0x04000000u)
		& (((PL & 0x08080808u) << 1) + ((PH & 0x00000008u) >> 3)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x000001f0f0703010ULL) & 0x0000080808080800ULL;

	outflank_h = OUTFLANK_3[(OH >> 17) & 0x3f] & (PH >> 16);
	flipped |= FLIPPED_3_H[outflank_h] & 0x00ff000000000000ULL;

	outflank_d = OUTFLANK_3[(((OH & 0x00081422u) + (OL & 0x40000000u)) * 0x01010101u) >> 25]
		& ((((PH & 0x00081422u) + (PL & 0x41800000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_3_H[outflank_d] & 0x0008142240000000ULL;	// A4D7H3

	return flipped;
}

/**
 * Compute flipped discs when playing on square E7.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_E7(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d;
	unsigned long long flipped;

	outflank_v = ((((OL & 0x10101000u) + ((OH & 0x00001010u) >> 4)) * 0x08040201u + 0x04000000u)
		& ((PL & 0x10101010u) + ((PH & 0x00000010u) >> 4)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x000003e1e0e06020ULL) & 0x0000101010101000ULL;

	outflank_h = OUTFLANK_4[(OH >> 17) & 0x3f] & (PH >> 16);
	flipped |= FLIPPED_4_H[outflank_h] & 0x00ff000000000000ULL;

	outflank_d = OUTFLANK_4[(((OH & 0x00102844u) + (OL & 0x02000000u)) * 0x01010101u) >> 25]
		& ((((PH & 0x00102844u) + (PL & 0x82010000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_4_H[outflank_d] & 0x0010284402000000ULL;	// A3E7H4

	return flipped;
}

/**
 * Compute flipped discs when playing on square F7.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_F7(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x20202000u) >> 1) + ((OH & 0x00002020u) >> 5)) * 0x08040201u + 0x04000000u)
		& (((PL & 0x20202020u) >> 1) + ((PH & 0x00000020u) >> 5)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x000007c3c1c0c040ULL) & 0x0000202020202000ULL;

	outflank_h = OUTFLANK_5[(OH >> 17) & 0x3f] & (PH >> 16);
	flipped |= FLIPPED_5_H[outflank_h] & 0x00ff000000000000ULL;

	outflank_d = OUTFLANK_5[(((OH & 0x00205008u) + (OL & 0x04020000u)) * 0x01010101u) >> 25]
		& ((((PH & 0x00205088u) + (PL & 0x04020100u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_5_H[outflank_d] & 0x0020500804020000ULL;	// A2F7H5

	return flipped;
}

/**
 * Compute flipped discs when playing on square G7.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_G7(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d9;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x40404000u) >> 2) + ((OH & 0x00004040u) >> 6)) * 0x08040201u + 0x04000000u)
		& (((PL & 0x40404040u) >> 2) + ((PH & 0x00000040u) >> 6)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x00000f8783818080ULL) & 0x0000404040404000ULL;

	outflank_h = OUTFLANK_7[(OH >> 16) & 0x3e] & (PH >> 15);
	flipped |= (unsigned long long) ((-outflank_h) & 0x3e) << 48;

	outflank_d9 = OUTFLANK_7[(((OL & 0x08040200u) + (OH & 0x00002010u)) * 0x01010101u) >> 24]
		& ((((PL & 0x08040201u) + (PH & 0x00000010u)) * 0x01010101u) >> 23);
	flipped |= ULL((outflank_d9 * 0x00001f0fu) & 0x00002010u, (outflank_d9 * 0x07030100u) & 0x08040200u);

	return flipped;
}

/**
 * Compute flipped discs when playing on square H7.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_H7(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d9, flippedH, flippedL;

	outflank_v = (((((OL & 0x80808000u) >> 3) + ((OH & 0x00008080u) >> 7)) * 0x08040201u + 0x04000000u)
		& (((PL & 0x80808080u) >> 3) + ((PH & 0x00000080u) >> 7)) * 0x08040201u) >> 24;
	flippedH = (outflank_v * 0x00001f0fu) & 0x00008080u;
	flippedL = (outflank_v * 0x07030100u) & 0x80808000u;

	outflank_h = OUTFLANK_7[(OH >> 17) & 0x3f] & (PH >> 16);
	flippedH |= ((-outflank_h) & 0x3f) << 17;

	outflank_d9 = OUTFLANK_7[(((OL & 0x10080400u) + (OH & 0x00004020u)) * 0x01010101u) >> 25]
		& ((((PL & 0x10080402u) + (PH & 0x00000020u)) * 0x01010101u) >> 24);
	flippedH |= (outflank_d9 * 0x00003e1eu) & 0x00004020u;
	flippedL |= (outflank_d9 * 0x0e060200u) & 0x10080400u;

	return ULL(flippedH, flippedL);
}

/**
 * Compute flipped discs when playing on square A8.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_A8(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_v, outflank_h, outflank_d7;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x01010100u) << 4) + (OH & 0x00010101u)) * 0x08040201u + 0x02000000u)
		& (((PL & 0x01010101u) << 4) + (PH & 0x00000101u)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x00007e3e1e0e0602ULL) & 0x0001010101010100ULL;

	outflank_h = ((OH & 0x7e000000u) + 0x02000000u) & PH;
	flipped |= (unsigned long long) ((outflank_h - (outflank_h >> 8)) & 0x7e000000u) << 32;

	outflank_d7 = ((((OL & 0x10204000u) + (OH & 0x00020408u)) * 0x01010101u + 0x02000000u)
		& ((PL & 0x10204080u) + (PH & 0x00000408u)) * 0x01010101u) >> 24;
	flipped |= (outflank_d7 * 0x0000fcf8f0e0c080ULL) & 0x0002040810204000ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square B8.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_B8(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_v, outflank_h, outflank_d7;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x02020200u) << 3) + ((OH & 0x00020202u) >> 1)) * 0x08040201u + 0x02000000u)
		& (((PL & 0x02020202u) << 3) + ((PH & 0x00000202u) >> 1)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x0000fc7c3c1c0c04ULL) & 0x0002020202020200ULL;

	outflank_h = ((OH & 0x7c000000u) + 0x04000000u) & PH;
	flipped |= (unsigned long long) ((outflank_h - (outflank_h >> 8)) & 0x7c000000u) << 32;

	outflank_d7 = ((((OL & 0x20400000u) + (OH & 0x00040810u)) * 0x01010101u + 0x04000000u)
		& ((PL & 0x20408000u) + (PH & 0x00000810u)) * 0x01010101u) >> 25;
	flipped |= (outflank_d7 * 0x0001f9f1e1c18000ULL) & 0x0004081020400000ULL;

	return flipped;
}

/**
 * Compute flipped discs when playing on square C8.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_C8(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x04040400u) << 2) + ((OH & 0x00040404u) >> 2)) * 0x08040201u + 0x02000000u)
		& (((PL & 0x04040404u) << 2) + ((PH & 0x00000404u) >> 2)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x0001f8f878381808ULL) & 0x0004040404040400ULL;

	outflank_h = OUTFLANK_2[(OH >> 25) & 0x3f] & (PH >> 24);
	flipped |= FLIPPED_2_H[outflank_h] & 0xff00000000000000ULL;

	outflank_d = OUTFLANK_2[(((OH & 0x040a1020u) + (OL & 0x40000000u)) * 0x01010101u) >> 25]
		& ((((PH & 0x040a1120u) + (PL & 0x40800000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_2_H[outflank_d] & 0x040a102040000000ULL;	// A6C8H3

	return flipped;
}

/**
 * Compute flipped discs when playing on square D8.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_D8(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x08080800u) << 1) + ((OH & 0x00080808u) >> 3)) * 0x08040201u + 0x02000000u)
		& (((PL & 0x08080808u) << 1) + ((PH & 0x00000808u) >> 3)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x0003f1f0f0703010ULL) & 0x0008080808080800ULL;

	outflank_h = OUTFLANK_3[(OH >> 25) & 0x3f] & (PH >> 24);
	flipped |= FLIPPED_3_H[outflank_h] & 0xff00000000000000ULL;

	outflank_d = OUTFLANK_3[((OH & 0x08142240u) * 0x01010101u) >> 25]
		& ((((PH & 0x08142241u) + (PL & 0x80000000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_3_H[outflank_d] & 0x0814224000000000ULL;	// A5D8H4

	return flipped;
}

/**
 * Compute flipped discs when playing on square E8.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_E8(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d;
	unsigned long long flipped;

	outflank_v = ((((OL & 0x10101000u) + ((OH & 0x00101010u) >> 4)) * 0x08040201u + 0x02000000u)
		& ((PL & 0x10101010u) + ((PH & 0x00001010u) >> 4)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x0007e3e1e0e06020ULL) & 0x0010101010101000ULL;

	outflank_h = OUTFLANK_4[(OH >> 25) & 0x3f] & (PH >> 24);
	flipped |= FLIPPED_4_H[outflank_h] & 0xff00000000000000ULL;

	outflank_d = OUTFLANK_4[((OH & 0x10284402u) * 0x01010101u) >> 25]
		& ((((PH & 0x10284482u) + (PL & 0x01000000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_4_H[outflank_d] & 0x1028440200000000ULL;	// A4E8H5

	return flipped;
}

/**
 * Compute flipped discs when playing on square F8.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_F8(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x20202000u) >> 1) + ((OH & 0x00202020u) >> 5)) * 0x08040201u + 0x02000000u)
		& (((PL & 0x20202020u) >> 1) + ((PH & 0x00002020u) >> 5)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x000fc7c3c1c0c040ULL) & 0x0020202020202000ULL;

	outflank_h = OUTFLANK_5[(OH >> 25) & 0x3f] & (PH >> 24);
	flipped |= FLIPPED_5_H[outflank_h] & 0xff00000000000000ULL;

	outflank_d = OUTFLANK_5[(((OH & 0x20500804u) + (OL & 0x02000000u)) * 0x01010101u) >> 25]
		& ((((PH & 0x20508804u) + (PL & 0x02010000u)) * 0x01010101u) >> 24);
	flipped |= FLIPPED_5_H[outflank_d] & 0x2050080402000000ULL;	// A3F8H6

	return flipped;
}

/**
 * Compute flipped discs when playing on square G8.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_G8(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d9;
	unsigned long long flipped;

	outflank_v = (((((OL & 0x40404000u) >> 2) + ((OH & 0x00404040u) >> 6)) * 0x08040201u + 0x02000000u)
		& (((PL & 0x40404040u) >> 2) + ((PH & 0x00004040u) >> 6)) * 0x08040201u) >> 24;
	flipped = (outflank_v * 0x001f8f8783818080ULL) & 0x0040404040404000ULL;

	outflank_h = OUTFLANK_7[(OH >> 24) & 0x3e] & (PH >> 23);
	flipped |= (unsigned long long) ((-outflank_h) & 0x3e) << 56;

	outflank_d9 = OUTFLANK_7[(((OL & 0x04020000u) + (OH & 0x00201008u)) * 0x01010101u) >> 24]
		& ((((PL & 0x04020100u) + (PH & 0x00001008u)) * 0x01010101u) >> 23);
	flipped |= ULL((outflank_d9 * 0x001f0f07u) & 0x00201008u, (outflank_d9 * 0x03010000u) & 0x04020000u);

	return flipped;
}

/**
 * Compute flipped discs when playing on square H8.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_H8(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	unsigned int outflank_h, outflank_v, outflank_d9, flippedH, flippedL;

	outflank_v = (((((OL & 0x80808000u) >> 3) + ((OH & 0x00808080u) >> 7)) * 0x08040201u + 0x02000000u)
		& (((PL & 0x80808080u) >> 3) + ((PH & 0x00008080u) >> 7)) * 0x08040201u) >> 24;
	flippedH = (outflank_v * 0x003f1f0fu) & 0x00808080u;
	flippedL = (outflank_v * 0x07030100u) & 0x80808000u;

	outflank_h = OUTFLANK_7[(OH >> 25) & 0x3f] & (PH >> 24);
	flippedH |= ((-outflank_h) & 0x3f) << 25;

	outflank_d9 = OUTFLANK_7[(((OL & 0x08040200u) + (OH & 0x00402010u)) * 0x01010101u) >> 25]
		& ((((PL & 0x08040201u) + (PH & 0x00002010u)) * 0x01010101u) >> 24);
	flippedH |= (outflank_d9 * 0x007e3e1eu) & 0x00402010u;
	flippedL |= (outflank_d9 * 0x0e060200u) & 0x08040200u;

	return ULL(flippedH, flippedL);
}

/**
 * Compute (zero-) flipped discs when plassing.
 *
 * @param P player's disc pattern.
 * @param O opponent's disc pattern.
 * @return flipped disc pattern.
 */
static unsigned long long flip_pass(unsigned int PL, unsigned int PH, unsigned int OL, unsigned int OH)
{
	(void) PL; // useless code to shut-up compiler warning
	(void) PH;
	(void) OL;
	(void) OH;
	return 0;
}


/** Array of functions to compute flipped discs */
unsigned long long (*flip[])(unsigned int, unsigned int, unsigned int, unsigned int) = {
#ifdef hasSSE2
	flip_sse_A1, flip_sse_B1, flip_sse_C1, flip_sse_D1, flip_sse_E1, flip_sse_F1, flip_sse_G1, flip_sse_H1,
	flip_sse_A2, flip_sse_B2, flip_sse_C2, flip_sse_D2, flip_sse_E2, flip_sse_F2, flip_sse_G2, flip_sse_H2,
	flip_sse_A3, flip_sse_B3, flip_sse_C3, flip_sse_D3, flip_sse_E3, flip_sse_F3, flip_sse_G3, flip_sse_H3,
#else
	flip_A1, flip_B1, flip_C1, flip_D1, flip_E1, flip_F1, flip_G1, flip_H1,
	flip_A2, flip_B2, flip_C2, flip_D2, flip_E2, flip_F2, flip_G2, flip_H2,
	flip_A3, flip_B3, flip_C3, flip_D3, flip_E3, flip_F3, flip_G3, flip_H3,
#endif
	flip_A4, flip_B4, flip_C4, flip_D4, flip_E4, flip_F4, flip_G4, flip_H4,
	flip_A5, flip_B5, flip_C5, flip_D5, flip_E5, flip_F5, flip_G5, flip_H5,
	flip_A6, flip_B6, flip_C6, flip_D6, flip_E6, flip_F6, flip_G6, flip_H6,
	flip_A7, flip_B7, flip_C7, flip_D7, flip_E7, flip_F7, flip_G7, flip_H7,
	flip_A8, flip_B8, flip_C8, flip_D8, flip_E8, flip_F8, flip_G8, flip_H8,
	flip_pass, flip_pass
};

#if defined(USE_GAS_MMX) && !defined(hasSSE2)

static unsigned long long (*flip_sse_123[])(unsigned int, unsigned int, unsigned int, unsigned int) = {
	flip_sse_A1, flip_sse_B1, flip_sse_C1, flip_sse_D1, flip_sse_E1, flip_sse_F1, flip_sse_G1, flip_sse_H1,
	flip_sse_A2, flip_sse_B2, flip_sse_C2, flip_sse_D2, flip_sse_E2, flip_sse_F2, flip_sse_G2, flip_sse_H2,
	flip_sse_A3, flip_sse_B3, flip_sse_C3, flip_sse_D3, flip_sse_E3, flip_sse_F3, flip_sse_G3, flip_sse_H3
};

void init_flip_sse(void) {
	memcpy(&flip[0], flip_sse_123, sizeof(flip_sse_123));
}
#endif
